package cc.aiee.alipay.core.tool;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;

import cc.aiee.alipay.config.AliPayConfig;
import cc.aiee.alipay.core.pojo.dto.AliPayAppNotifyDTO;
import cc.aiee.alipay.core.pojo.dto.AliPayNotifyFreezeDTO;
import cc.aiee.core.kit.KitJson;
import cc.aiee.core0.bean.R;
import cc.aiee.core0.enums.MsgCodeEnum;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AliPayNotifyTool {
	/**
	 *  弃用,签名中的+号自动转换成了空格,慎用
	 * @param request
	 * @return
	 */
	public Map<String, String> notifyAppDTO(HttpServletRequest request) {
		// 获取支付宝POST过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		Map<String, String[]> requestParams = request.getParameterMap();

		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决，这段代码在出现乱码时使用。
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);
		}
		return params;
	}

	public Map<String, String> notifyFreezeDTO(HttpServletRequest request) {
		String queryString = request.getQueryString();
		if(StrUtil.isBlank(queryString)) {
			log.info("支付宝通知参数中:queryString 为空");
			return notifyAppDTO(request);
		}
		// 对待签名字符串数据通过&进行拆分
		String[] temp = queryString.split("&");
		Map<String, String> map = new HashMap<String, String>();
		// 把拆分数据放在map集合内
		for (int i = 0; i < temp.length; i++) {
			String[] arr = temp[i].split("=", 2); // 通过"="号分割成2个数据
			String[] tempAagin = new String[arr.length]; // 再开辟一个数组用来接收分割后的数据
			for (int j = 0; j < arr.length; j++) {
				tempAagin[j] = arr[j];
			}
			String value = tempAagin[1];
			if (false == StrUtil.startWithIgnoreCase(tempAagin[0], "sign")) {
				value = URLDecoder.decode(value, CharsetUtil.CHARSET_UTF_8);
			}
			map.put(tempAagin[0], value);
		}
		return map;
	}

	public R<AliPayAppNotifyDTO> notifyAppDTO(Map<String, String> params, AliPayConfig config) {
		// 切记alipaypublickey是支付宝的公钥，请去open.alipay.com对应应用下查看。
		// boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String
		// publicKey, String charset, String sign_type)

//		StandardCharsets.UTF_8;
		try {
			boolean signVerified = AlipaySignature.rsaCheckV1(params, config.getAlipayPublicKey(), CharsetUtil.UTF_8,
					"RSA2");
			if (signVerified == false) {
				log.error("AliPaySignVerified:签名验证失败,body:{}", KitJson.toJSONString(params));
				return new R<>(MsgCodeEnum.F_SIGN_6);
			}

			AliPayAppNotifyDTO mapToBean = BeanUtil.mapToBean(params, AliPayAppNotifyDTO.class, false);
			return new R<>(MsgCodeEnum.SUCCESS, mapToBean);
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return new R<>(MsgCodeEnum.F_EXCEPTION_2);
	}

	public R<AliPayNotifyFreezeDTO> notifyFreezeDTO(Map<String, String> params, AliPayConfig config) {
		try {
			String charset = params.get("charset");
			if (StrUtil.isBlank(charset) || StrUtil.equals("UTF-8", charset, true)) {
				charset = CharsetUtil.UTF_8;
			}
			String sign_type = params.get("sign_type");
			if (StrUtil.isBlank(sign_type) || StrUtil.equals("RSA2", sign_type, true)) {
				sign_type = "RSA2";
			}
			boolean signVerified = AlipaySignature.rsaCheckV1(params, config.getAlipayPublicKey(), charset, sign_type);
			if (signVerified == false) {
				log.error("AliPaySignVerified:签名验证失败,body:{}", KitJson.toJSONString(params));
				return new R<>(MsgCodeEnum.F_SIGN_6);
			}

			AliPayNotifyFreezeDTO mapToBean = BeanUtil.mapToBean(params, AliPayNotifyFreezeDTO.class, false);
			return new R<>(MsgCodeEnum.SUCCESS, mapToBean);
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return new R<>(MsgCodeEnum.F_EXCEPTION_2);
	}

	public static String notifyReturn() {
		return "success";
	}
}
